package com.meta.act.app.service.impl;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.meta.act.app.domain.system.SysUserDo;
import com.meta.act.app.domain.tenant.TenantMenuRelateDo;
import com.meta.act.app.domain.tenant.TenantUserDo;
import com.meta.act.entity.SysMenu;
import com.meta.framework.domain.event.DomainEventPulish;
import com.meta.act.app.event.TenantCreateEvent;
import com.meta.act.app.service.*;
import com.meta.act.app.system.repository.*;
import com.meta.act.app.tenant.entity.*;
import com.meta.framework.common.constant.UserConstants;
import com.meta.act.entity.SysDept;
import com.meta.framework.act.entity.SysUser;
import com.meta.framework.common.exception.BaseException;
import com.meta.framework.common.utils.SecurityUtils;
import com.meta.framework.define.DelFlagEnum;
import com.meta.framework.exception.PlatformErrorCode;
import com.meta.act.app.domain.tenant.TenantDo;
import com.meta.act.app.tenant.exception.TenantException;
import com.meta.act.app.tenant.req.TenantAddUserCmd;
import com.meta.act.app.tenant.req.TenantCreateCmd;
import com.meta.act.app.tenant.req.TenantEditCmd;
import com.meta.act.app.tenant.req.TenantEditUserCmd;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 租户信息表
 *
 * @Title: TenantBaseAppServiceImpl
 * @Author: Simon
 * @Remark: The modified content
 * @CreateDate: 2020-11-04 15:23:04
 * @Version: v2.0
 */
@Service
@Slf4j
public class TenantAppServiceImpl implements TenantAppService {
	@Autowired
	private TenantBaseRepository tenantBaseRepository;
	@Autowired
	private TenantExtRepository tenantExtRepository;
	@Autowired
	private TenantFileRepository tenantFileRepository;
	@Autowired
	private TenantUserRepository tenantUserRepository;

	@Autowired
	private ISysDeptService deptService;

	@Autowired
	private ISysUserService userService;

	@Autowired
	private ISysMenuService iSysMenuService;

	@Autowired
	private TenantMenuRelateRepository tenantMenuRelateRepository;

	@Autowired
	private ISysUserService iSysUserService;

	@Autowired
	private ISysConfigService configService;

	@Autowired
	private ISysRoleService iSysRoleService;
	
	@Autowired
	private DomainEventPulish domainEventPulish;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Long save(TenantCreateCmd cmd) {
		TenantDo tenantBaseDo = TenantDo.of(cmd);
		TenantBase tenantBase = tenantBaseDo.transform(TenantBase.class);
		tenantBaseRepository.insertTenantBase(tenantBase);
		Long tenantId = tenantBase.getTenantId();
		TenantDo tenantDo = TenantDo.of(cmd, tenantId);
		if (tenantId > 0) {
			//保存租户扩展信息
			tenantExtRepository.insertTenantExt(tenantDo.getTenantExtDo().transform(TenantExt.class));
			//保存文件
			List<TenantFile> tenantFiles = new ArrayList<>();
			tenantDo.getTaxFileList().forEach(x -> {
				tenantFiles.add(x.transform(TenantFile.class));
				tenantFileRepository.batchInsertTenantFile(tenantFiles);
			});
			List<TenantFile> creditFileList = new ArrayList<>();
			tenantDo.getCreditFileList().forEach(x -> {
				creditFileList.add(x.transform(TenantFile.class));
				tenantFileRepository.batchInsertTenantFile(creditFileList);
			});
			initTenantMenu(tenantId);
			Long deptId = initTenantDept(tenantId, cmd.getName());
			Long rootRoleId = initTenantAdminRole(tenantId, deptId);
			initTenantAdmin(tenantId, cmd.getLinkTel(), cmd.getLinkNickName(), deptId, rootRoleId);
			
			TenantCreateEvent.of(tenantBase).publish();
			return tenantId;
		}
		return null;
	}

	private Long initTenantAdminRole(Long tenantId, Long deptId) {

		List<SysMenu> sysMenus = iSysMenuService.listTenantVisibleMenu();
		return iSysRoleService.initTenantAdminRole(tenantId, deptId, sysMenus);
	}

	@Transactional(rollbackFor = Exception.class)
	public void initTenantAdmin(Long tenantId, String telephone, String nickName, Long deptId, Long roleId) {

		String password = configService.selectConfigByKey("sys.user.initPassword");
		iSysUserService.insertUser(SysUserDo.ofAdmin(password, telephone, nickName, tenantId, deptId, roleId));
	}

	@Transactional(rollbackFor = Exception.class)
	public void initTenantMenu(Long tenantId) {

		List<SysMenu> sysMenus = iSysMenuService.listTenantVisibleMenu();
		sysMenus = Optional.ofNullable(sysMenus).orElse(Lists.newArrayList());
		List<TenantMenuRelateDo> tenantMenuRelateDos = TenantMenuRelateDo.of(sysMenus, tenantId);
		tenantMenuRelateRepository.batchInsertTenantMenuRelate(tenantMenuRelateDos.stream().map(x -> x.transform(TenantMenuRelate.class)).collect(Collectors.toList()));
	}

	@Transactional(rollbackFor = Exception.class)
	public Long initTenantDept(Long tenantId, String orgName) {

		SysDept dept = new SysDept();
		dept.setParentId(0L);
		dept.setAncestors("0");
		dept.setDeptName(orgName);
		dept.setTenantId(tenantId);
		try {
			// 添加租户时，创建根组织
			if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
				//return CommonRes.error("新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
				throw new BaseException("创建部门失败");
			}
			dept.setCreateBy(SecurityUtils.getUsername());
			deptService.initRootDept(dept);
			return dept.getDeptId();
		} catch (Exception e) {
			log.error("createOrg, param:{}, error.", JSON.toJSONString(dept), e);
			throw new BaseException("初始化租户部门错误");
		}
	}

	@Override
	public void edit(TenantEditCmd cmd) {
		TenantDo tenantDo = tenantBaseRepository.getTenantDo(cmd.getTenantId());
		tenantDo.edit(cmd);
		tenantBaseRepository.updateTenantBase(tenantDo.transform(TenantBase.class));
		tenantExtRepository.updateTenantExt(tenantDo.getTenantExtDo().transform(TenantExt.class));
		TenantFile tenantFile = new TenantFile();
		tenantFile.setTenantId(cmd.getTenantId());
		tenantFile.setDelFlag(DelFlagEnum.I.getCode());
		tenantFileRepository.updateTenantFile(tenantFile);

		//保存文件
		List<TenantFile> tenantFiles = new ArrayList<>();
		tenantDo.getTaxFileList().forEach(x -> {
			x.setTenantId(cmd.getTenantId());
			tenantFiles.add(x.transform(TenantFile.class));
		});
		tenantDo.getCreditFileList().forEach(x -> {
			x.setTenantId(cmd.getTenantId());
			tenantFiles.add(x.transform(TenantFile.class));
		});
		tenantFileRepository.batchInsertTenantFile(tenantFiles);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addUser(TenantAddUserCmd cmd) {
		// 获取前端传递过来的选中角色信息
		// 用户是否存在，不存在则创建用户
		SysUser user = userService.selectUserByUserName(cmd.getMobile());
		Long userId = null;
		if (user == null) {
			// 新增租户用户信息
			SysUser sysUser = new SysUser();
			sysUser.setUserName(cmd.getMobile());
			sysUser.setPassword(TenantAppServiceImpl.initPwd(cmd.getMobile()));
			sysUser.setNickName(cmd.getUserNameZh());
			// 初始化用户：获取部门信息
			SysDept dept = new SysDept();
			dept.setParentId(0L);
			dept.setTenantId(cmd.getTenantId());
			List<SysDept> orgList = deptService.selectDeptList(dept);
			if (!CollectionUtils.isEmpty(orgList)) {
				sysUser.setDeptId(orgList.get(0).getDeptId());
			}
			// 初始化用户:创建用户相关角色部门信息
			sysUser.setRoleIds((Long[]) Arrays.asList(cmd.getRoleCode()).toArray());
			userService.insertUser(sysUser);
			// 增加租户用户关联信息
			createTenantUser(sysUser);
		} else {
			log.info("该用户已经存在");
			return;
		}
	}

	/**
	 * 创建租户用户信息
	 * @method      createTenantUser
	 * @param       user:
	 * @return      int
	 * @author      M.simple
	 * @date        2020/11/25 3:00 下午
	 * @version     v2.0
	 */
	@Override
	public int createTenantUser(SysUser user){
		TenantUser tenantUser = tenantUserRepository.getTenantUser(user.getUserId(), user.getTenantId());
		if(Optional.ofNullable(tenantUser).isPresent()){
			throw new BaseException("新增用户'" + user.getPhonenumber() + "'失败，手机号码已存在");
		}
		TenantUserDo tenantUserDo = TenantUserDo.of(user.getUserId(), user.getTenantId(), user.getDeptId());
		return tenantUserRepository.insertTenantUser(tenantUserDo);
	}

	@Override
	public int deleteUserByIds(List<Long> userIds){
		userIds.forEach(x -> {
			TenantUser tenantUser = tenantUserRepository.getTenantUser(x, SecurityUtils.getLoginUser().getTenantId());
			TenantUserDo tenantUserDo = tenantUser.transform(TenantUserDo.class);
			tenantUserDo.deleteTenantUser();
			tenantUserRepository.updateTenantUserByPk(tenantUserDo);
		});

		return 1;
	};

	@Override
	public void updateDept(Long userId, Long deptId){

		TenantUser tenantUser = tenantUserRepository.getTenantUser(userId, SecurityUtils.getLoginUser().getTenantId());
		TenantUserDo tenantUserDo = tenantUser.transform(TenantUserDo.class);
		tenantUserDo.chageDept(deptId);
		tenantUserRepository.updateTenantUserByPk(tenantUserDo);
	}

	@Override
	public void editUser(TenantEditUserCmd cmd) {
		//1、用户是否存在
		SysUser user = userService.selectUserByUserName(cmd.getMobile());
		//手机号码未被使用，直接修改
		if (user != null && user.getUserId() != null && !user.getUserId().equals(cmd.getUserId() + "")) {
			throw new TenantException(PlatformErrorCode.RESULT_EXIST_MOBILE);
		} else {
			//修改姓名
			SysUser sysUser = new SysUser();
			sysUser.setUserId(cmd.getUserId());
			sysUser.setUserName(cmd.getMobile());
			sysUser.setRoleIds((Long[]) Arrays.asList(cmd.getRoleCode()).toArray());
			userService.updateUser(sysUser);
		}
		//  更新租户用户信息
		TenantUser tenantUser = new TenantUser();
		tenantUser.setStatus(cmd.getStatus());
		tenantUser.setTenantId(cmd.getTenantId());
		tenantUser.setUserId(cmd.getUserId());
		tenantUserRepository.updateTenantUser(tenantUser);
	}

	public static String initPwd(String mobile) {
		if (StringUtils.isEmpty(mobile) || mobile.length() <= 3) {
			return mobile;
		}
		return mobile.substring(0, 3) + mobile.substring(mobile.length() - 3, mobile.length());
	}

	public static void main(String[] args) {
		System.out.println(initPwd("18912972991"));
	}
}
